Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Python - [Pygame] PacMan mi perseguita(ritorno in base)
Forum - Python - [Pygame] PacMan mi perseguita(ritorno in base)

Avatar
3E8b12 (Normal User)
Newbie


Messaggi: 11
Iscritto: 08/11/2015

Segnala al moderatore
Postato alle 16:21
Giovedì, 19/11/2015
Salve a tutti, dopo aver posto la domanda sulle matrici in c++ (e aver ottenuto validissime solzioni che però ho applicato solo su scacchiere) ho deciso di riprodurre l'intero gioco di PacMan (ma in python), e ci sono (quasi) riuscito, il gioco funziona perfettamente, ma odio con anima e corpo quei dannati muri :grr:.
Mi spiego, e spero di essere il più chiaro possibile:
Premetto di aver utilizzato le classi astratte.
All'interno del metodo __init__ del ghost ho dichiarato le seguenti variabili:
(chiaramente non posto ora TUTTO il codice completo del gioco, ma solo le porzioni interessate, spero comunque di poterlo fare nei prossimi giorni proprio su questo sito)
Codice sorgente - presumibilmente Python

  1. self._x, self._y = x, y
  2.         self._dx, self._dy = 0, 0#delta x e y
  3.  
  4.  
  5.         self._costante_x, self._costante_y = 110, 88#punto dove devo arrivare
  6.         self._attuale_x, self._attuale_y, self._w, self._h = self.rect()#il metodo rect mi restituisce sempre "x,y,w,h", ma a noi interessano solo x e y in questo caso
  7.  
  8.  
  9.         self._COmAT_x = self._costante_x - self._attuale_x#COSTANTE meno ATTUALE X
  10.         self._COmAT_y = self._costante_y - self._attuale_y#COSTANTE meno ATTUALE Y


Io quindi ho una classe Ghost, con il proprio metodo collide, rect, movimento ecc..
Il metodo movimento è sempre in funzione, quindi bisognerebbe immaginarlo COME SE FOSSE un ciclo, e questo è un codice FUNZIONANTE solo se non si tengono in considerazione i muri al momento della "morte" dei fantasmi (ma io voglio una copia fedele del gioco :heehee: )
Codice sorgente - presumibilmente Python

  1. def movimento(self):
  2.             self._attuale_x, self._attuale_y, self._w, self._h = self.rect()
  3.             self._COmAT_x = self._costante_x - self._attuale_x
  4.             self._COmAT_y = self._costante_y - self._attuale_y
  5.            
  6.             if self._COmAT_x < 0:
  7.                 self._x = self._x - 2
  8.                        
  9.             elif self._COmAT_x > 0:
  10.                 self._x = self._x + 2
  11.                        
  12.             if self._COmAT_y < 0:
  13.                 self._y = self._y - 2
  14.                        
  15.             elif self._COmAT_y > 0:
  16.                 self._y = self._y + 2


premessa, ovviamente ho già un metodo di nome GTW(GoingToWall) che mi dice se sto andando o meno su un muro.
Ad esempio:
Codice sorgente - presumibilmente Python

  1. if not (GTW(ClasseAstratta,self,[b]self._DX[/b], [b]self._DY[/b])):


che si traduce in "SE NON TI SCONTRI CONTRO UN MURO.
Scrivo questo post di fretta, quindi nell'eventualità di aver omesso un dettaglio importante, o di non essere stato abbastanza chiaro, fatemelo sapere.


3E8b12 ha allegato un file: pacman_background.png (1641 bytes)
Clicca qui per guardare l'immagine

Ultima modifica effettuata da 3E8b12 il 19/11/2015 alle 16:23
PM Quote
Avatar
HeDo (Founder Member)
Guru^2


Messaggi: 2765
Iscritto: 21/09/2007

Segnala al moderatore
Postato alle 9:59
Venerdì, 20/11/2015
mi dispiace ma non si è capito molto, aggiungi dei dettagli altrimenti non possiamo aiutarti

PM Quote
Avatar
3E8b12 (Normal User)
Newbie


Messaggi: 11
Iscritto: 08/11/2015

Segnala al moderatore
Postato alle 17:47
Venerdì, 20/11/2015
Testo quotato

Postato originariamente da HeDo:

mi dispiace ma non si è capito molto, aggiungi dei dettagli altrimenti non possiamo aiutarti


Sì, scusami ;).
In sostanza, tenendo conto di avere un punto A e un punto B, come faccio a tracciare il percorso che il Ghost deve seguire al momento della morte, tenendo conto dei muri proprio della mappa di pacman?
Io nella versione attuale riesco a farli tornare in base solamente facendogli seguire un percorso retto, e rendendo i muri "incosistenti" fino alla "rigenerazione".
Proprio non mi viene semplice fargli seguire il percorso più breve della mappa...

PM Quote
Avatar
HeDo (Founder Member)
Guru^2


Messaggi: 2765
Iscritto: 21/09/2007

Segnala al moderatore
Postato alle 18:16
Venerdì, 20/11/2015
Semplicemente perchè ti manca un po di teoria di base.
Qui c'è la formalizzazione del tuo problema e anche alcuni algoritmi che lo risolvono

https://en.wikipedia.org/wiki/Shortest_path_problem

PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 449
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 21:42
Venerdì, 20/11/2015
Senza scomodare troppo grafi eccetera (anche se ti consiglio di studiarli bene, prima o poi servono), un modo semplice potrebbe essere quello di determinare prima che inizi la partita il percorso che da una casella porta al centro.

WARNING: mi è balenata in testa ora, non garantisco nulla

per ogni casella definisci due cose:
1) distanza minima dall'ingresso del box in centro (numero intero >= 0)
2) direzione di percorrenza (le quattro direzioni oppure fermo, capirai poi perché)

(di fatto mi sto definendo un potenziale e un gradiente discreto, si vede che qualcosa di analisi 2 mi sta entrando in testa :| )

L'algoritmo è una cosa simile (pseudocodice):
Codice sorgente - presumibilmente Python

  1. def calcola_matrice_movimento(griglia_gioco, nodi, (x_safe, y_safe, w_safe, h_safe)):
  2.     dist = array bidimensionale con le stesse dimensioni di griglia_gioco # all'inizio tutti -1
  3.     dir = array bidimensionale con le stesse dimensioni di griglia_gioco
  4.  
  5.     # inizializzazione: marcare la zona safe dove i fantasmini staranno fermi
  6.     for x in range(x_safe, x_safe+w_safe):
  7.         for y in range(y_safe, y_safe+h):
  8.             dir[x][y] = fermo
  9.             dist[x][y] = 0
  10.  
  11.     while len(nodi) > 0:
  12.         nodo = nodi.pop() # sarebbe meglio estrarre il primo nodo, ma le liste python fanno schifo
  13.         best_dir = None
  14.         min_dist = float('inf')
  15.         for x, y, direzione in nodi_adiacenti(griglia_gioco, x, y): # nodi
  16.             if not muro(x, y):
  17.                 if dist[x][y] != -1: #nodo già processato
  18.                     if dist[x][y] < min_dist:
  19.                         min_dist = dist[x][y]
  20.                         best_dir = direzione # nota: direzione è la direzione da 'nodo' al nodo (x,y)
  21.                     else:
  22.                         nodi.append(nodo) # il nodo verrà processato dopo
  23.         dir[x_nodo][y_nodo] = best_dir
  24.         dist[x_nodo][y_nodo] = min_dist + 1
  25.  
  26.     return dir


Devi chiamare la funzioni usando come argomento 'nodi' il nodo (o i nodi) che si affacciano sulla zona safe (la porta in pratica).
A questo punto ti basta usare la matrice risultante per muoverti (ogni volta devi seguire la "freccia" indicata).
L'unica difficoltà sono le funzioni che prendono i nodi adiacenti considerando bordi & so on


Ultima modifica effettuata da lumo il 20/11/2015 alle 21:45
PM Quote
Avatar
3E8b12 (Normal User)
Newbie


Messaggi: 11
Iscritto: 08/11/2015

Segnala al moderatore
Postato alle 18:46
Giovedì, 26/11/2015
Testo quotato

Semplicemente perchè ti manca un po di teoria di base.
Qui c'è la formalizzazione del tuo problema e anche alcuni algoritmi che lo risolvono

https://en.wikipedia.org/wiki/Shortest_path_problem


Grazie per il suggerimento ;)
Testo quotato

Postato originariamente da lumo:

Senza scomodare troppo grafi eccetera (anche se ti consiglio di studiarli bene, prima o poi servono), un modo semplice potrebbe essere quello di determinare prima che inizi la partita il percorso che da una casella porta al centro.

WARNING: mi è balenata in testa ora, non garantisco nulla

per ogni casella definisci due cose:
1) distanza minima dall'ingresso del box in centro (numero intero >= 0)
2) direzione di percorrenza (le quattro direzioni oppure fermo, capirai poi perché)

(di fatto mi sto definendo un potenziale e un gradiente discreto, si vede che qualcosa di analisi 2 mi sta entrando in testa :| )

L'algoritmo è una cosa simile (pseudocodice):
Codice sorgente - presumibilmente Python

  1. def calcola_matrice_movimento(griglia_gioco, nodi, (x_safe, y_safe, w_safe, h_safe)):
  2.     dist = array bidimensionale con le stesse dimensioni di griglia_gioco # all'inizio tutti -1
  3.     dir = array bidimensionale con le stesse dimensioni di griglia_gioco
  4.  
  5.     # inizializzazione: marcare la zona safe dove i fantasmini staranno fermi
  6.     for x in range(x_safe, x_safe+w_safe):
  7.         for y in range(y_safe, y_safe+h):
  8.             dir[x][y] = fermo
  9.             dist[x][y] = 0
  10.  
  11.     while len(nodi) > 0:
  12.         nodo = nodi.pop() # sarebbe meglio estrarre il primo nodo, ma le liste python fanno schifo
  13.         best_dir = None
  14.         min_dist = float('inf')
  15.         for x, y, direzione in nodi_adiacenti(griglia_gioco, x, y): # nodi
  16.             if not muro(x, y):
  17.                 if dist[x][y] != -1: #nodo già processato
  18.                     if dist[x][y] < min_dist:
  19.                         min_dist = dist[x][y]
  20.                         best_dir = direzione # nota: direzione è la direzione da 'nodo' al nodo (x,y)
  21.                     else:
  22.                         nodi.append(nodo) # il nodo verrà processato dopo
  23.         dir[x_nodo][y_nodo] = best_dir
  24.         dist[x_nodo][y_nodo] = min_dist + 1
  25.  
  26.     return dir


Devi chiamare la funzioni usando come argomento 'nodi' il nodo (o i nodi) che si affacciano sulla zona safe (la porta in pratica).
A questo punto ti basta usare la matrice risultante per muoverti (ogni volta devi seguire la "freccia" indicata).
L'unica difficoltà sono le funzioni che prendono i nodi adiacenti considerando bordi & so on



Scusami se rispondo solo ora, ma il tempo mi è avverso...
Ottimo, grazie mille :k:
Proverò questa soluzione più avanti, sicuramente potrà essermi utile anche per altro (oltre quelle "scartoffie" che sto già studiando).
Rifinisco alcuni semplici dettagli e carico qui il progetto, (anche se ho avuto problemi a caricare sorgenti:-?)
Testo quotato

si vede che qualcosa di analisi 2 mi sta entrando in testa :|


Io sono alle prese con analisi 1...:pat:

PM Quote